x86/crash: disable the watchdog NMIs on the crashing cpu
authorDavid Vrabel <david.vrabel@citrix.com>
Fri, 22 Nov 2013 13:48:12 +0000 (14:48 +0100)
committerJan Beulich <jbeulich@suse.com>
Fri, 22 Nov 2013 13:48:12 +0000 (14:48 +0100)
nmi_shootdown_cpus() is called during a crash to park all the other
CPUs.  This changes the NMI trap handlers which means there's no point
in having the watchdog still running.

This also disables the watchdog before executing any crash kexec image
and prevents the image from receiving unexpected NMIs.

Signed-off-by: David Vrabel <david.vrabel@citrix.com>
PVOps Linux as a kexec image shoots itself in the foot otherwise.

On a Core2 system, Linux declares a firmware bug and tries to invert some bits
in the performance counter register.  It ends up setting the number of retired
instructions to generate another NMI to fewer instructions than the NMI
interrupt path itself, and ceases to make any useful progress.

The call to disable_lapic_nmi_watchdog() must be this late into the kexec path
to be sure that this cpu is the one which will execute the kexec image.
Otherwise there are race conditions where the NMIs might be disabled on the
wrong cpu, resulting in the kexec image still receiving NMIs.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/crash.c
xen/arch/x86/nmi.c
xen/include/asm-x86/apic.h

index 4ef379b57fe1900b07dbbc8edc9d586e0419ac42..01fd906fd9e7aada6a36538f7c2d1e88d1dc71e1 100644 (file)
@@ -118,6 +118,7 @@ static void nmi_shootdown_cpus(void)
     unsigned long msecs;
     int i, cpu = smp_processor_id();
 
+    disable_lapic_nmi_watchdog();
     local_irq_disable();
 
     crashing_cpu = cpu;
index 2c16d937e0e3ed110d7b58ee3598bbdaca175073..c67a9c3c65255ae71120e4eb73ad013256e7387c 100644 (file)
@@ -165,7 +165,7 @@ static void nmi_timer_fn(void *unused)
     set_timer(&this_cpu(nmi_timer), NOW() + MILLISECS(1000));
 }
 
-static void disable_lapic_nmi_watchdog(void)
+void disable_lapic_nmi_watchdog(void)
 {
     if (nmi_active <= 0)
         return;
index dd528fb93daa815909b79908b25e1b92a3508a10..43b39cea4e77cd0cc46ba6fda905635dc967c20f 100644 (file)
@@ -200,6 +200,7 @@ extern void smp_local_timer_interrupt (struct cpu_user_regs *regs);
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
 extern void setup_apic_nmi_watchdog (void);
+extern void disable_lapic_nmi_watchdog(void);
 extern int reserve_lapic_nmi(void);
 extern void release_lapic_nmi(void);
 extern void self_nmi(void);